package com.leyou.item.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.leyou.common.dto.PageDTO;
import com.leyou.common.exception.LyException;
import com.leyou.item.dto.*;
import com.leyou.item.entity.*;
import com.leyou.item.mapper.SpuMapper;
import com.leyou.item.service.*;
import com.thoughtworks.xstream.mapper.Mapper;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


@Service
public class SpuServiceImpl extends ServiceImpl<SpuMapper, Spu> implements SpuService {

    @Autowired
    private BrandService brandService;

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private SpecGroupService SpecGroupService;

    @Autowired
    private SpecParamService specParamService;

    @Autowired
    private SpuDetailService spuDetailService;

    @Autowired
    private SkuService skuService;

    @Autowired
    private AmqpTemplate amqpTemplate;


    //分页查询spu表
    @Override
    public PageDTO<SpuDTO> querySpuPage(Long page, Long rows, Long brandId, Long categoryId, Long id, Boolean saleable) {

        IPage<Spu> spuPage = new Page<>(page, rows);

        //构建分页查询条件
        QueryWrapper<Spu> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .eq(brandId != null, "brand_id", brandId)
                .eq(categoryId != null, "cid3", categoryId)
                .eq(id != null, "id", id)
                .eq(saleable != null, "saleable", saleable);
        page(spuPage,queryWrapper);

        //获取查询spu集合
        List<SpuDTO> spuDTOList = SpuDTO.convertEntityList(spuPage.getRecords());

        for (SpuDTO spuDTO : spuDTOList) {
            String categoryNames = categoryService.queryCategoriesByIds(spuDTO.getCategoryIds())
                    .stream()
                    .map(CategoryDTO::getName)
                    .collect(Collectors.joining("/"));//Collectors.joining("/")将集合转换为以“/”拼接的字符串
            //TODO 考虑缓存
            //查询商品1级2级3级的分类名称，并set到spu集合中
            spuDTO.setCategoryName(categoryNames);
            //查询品牌名称，并set到spu集合中
            spuDTO.setBrandName(brandService.queryBrandById(spuDTO.getBrandId()).getName());
        }

        PageDTO<SpuDTO> spuDTOPageDTO = new PageDTO<>(spuPage.getTotal(), spuPage.getPages(),spuDTOList);
        return spuDTOPageDTO;
    }




//    //根据商品id(spuId),查询对应的规格参数组集合，以及规格参数组内参数的信息，和其对应的值value
//    @Override
//    public List<SpecGroupDTO> querySpuValuesBySpuId(Long spuId, Boolean searching) {
//
//        //根据商品id查询分类cid3
//        Long cid3 = this.getById(spuId).getCid3();
//
//        //根据商品分类cid3查询商品规格组信息
//        List<SpecGroupDTO> specGroupDTOList = SpecGroupService.querySpecGroupListByCategoryId(cid3);
//
//        //根据商品分类cid3查询商品规格信息
//        List<SpecParamDTO> specParamList = SpecParamDTO.convertEntityList(specParamService.query().eq("category_id", cid3).list());
//
//        //规格信息，跟据，规格组groupId进行分组，key为groupId,value为同groupId一组集合
//        Map<Long, List<SpecParamDTO>> listMap = specParamList
//                .stream()
//                .collect(Collectors.groupingBy(SpecParamDTO::getGroupId));
//
//        //将相同groupId组规格的，详细信息，放入规格组中
//        specGroupDTOList
//                .forEach(specGroupDTO -> specGroupDTO.setParams(listMap.get(specGroupDTO.getId())));
//
//        //根据商品supId获取规格参数的详细value信息getSpecification()
//        SpuDetail spuDetail = spuDetailService.getById(spuId);
//        //字符串无法使用，需要转换为json
//       String specification = spuDetail.getSpecification();
//        //key规格参数的id  value是规格参数的值在Specification字段中
//       Map<Long, Object> valueMap = JsonUtils.nativeRead(specification, new TypeReference<Map<Long, Object>>() {
//       });
//
//       //遍历商品规格信息集合,将Value值放入规格参数详细中
//        specParamList
//                .forEach(specParamDTO -> specParamDTO.setValue(valueMap.get(specParamDTO.getId())));
//
//
//        return specGroupDTOList;
//    }


    //根据商品spuID查询spu及sku、spuDetail等
    @Override
    public SpuDTO queryGoodsBySpuID(Long spuId) {
        //复用SpuDTO分页查询第一页，第一行+商品id --> 获取SpuDTO
        SpuDTO spuDTO = querySpuPage(1L, 1L, null, null, spuId, null)
                .getItems()
                .get(0);
        //根据商品spuId查询sku
        List<SkuDTO> skuDTOList = SkuDTO.convertEntityList(skuService.query().eq("spu_id", spuId).list());
        spuDTO.setSkus(skuDTOList);

        //根据商品spuId查询spuDetail
        SpuDetailDTO spuDetailDTO = spuDetailService.querySpuDetailBySpuID(spuId);
        spuDTO.setSpuDetail(spuDetailDTO);

        return spuDTO;
    }


    //根据商品spuID查询商品
    @Override
    public SpuDTO querySpuBySpuID(Long spuID) {
        return new SpuDTO(this.getById(spuID));
    }


    //修改商品上下架
    @Override
    @Transactional
    public void updateSaleable(Long supId, Boolean saleable) {
        //Spu上下架
        Spu spu = new Spu();
        spu.setId(supId);
        spu.setSaleable(saleable);
        spu.setUpdateTime(new Date());
        boolean flag = this.updateById(spu);
        if (!flag) {
            throw new LyException("Spu上下架失败", 500);
        }
        //Sku上下架
        boolean update = skuService.update(new UpdateWrapper<Sku>()
                .eq("spu_id", supId)
                .set(saleable != null, "saleable", saleable));

        if (!update) {
            throw new LyException("Sku上下架失败", 500);
        }

        //mq

        //声明路由key  当saleable为true时上架，false时下架
//        String routingKey = saleable ? "item.down" : "item.up";
        String routingKey = saleable ? "item.up" : "item.down";

        //向指定的交换机发送请求，消息内容为spuId
        this.amqpTemplate.convertAndSend("leyou.item",routingKey,supId);
        //mq接收消息的前提条件是这里的routingKey要对应到mq中的routingKey
    }

    @Override
    @Transactional
    public void addGoods(SpuDTO spuDTO) {

        if (CollectionUtils.isEmpty(spuDTO.getSkus())) {
            throw new LyException("每个sku下至少一个spu", 400);
        }

        //新增Spu表
        Spu spu = spuDTO.toEntity(Spu.class);
        this.save(spu);
        Long spuId = spu.getId();

        //新增SpuDetail表
        SpuDetail spuDetail = spuDTO.getSpuDetail().toEntity(SpuDetail.class);
        spuDetail.setSpuId(spuId);
        this.spuDetailService.save(spuDetail);

        //新增Sku表
        List<SkuDTO> skuDTOList = spuDTO.getSkus();
        for (SkuDTO skuDTO : skuDTOList) {
            Sku sku = skuDTO.toEntity(Sku.class);
            sku.setSpuId(spuId);
            sku.setSaleable(true);
            this.skuService.save(sku);
        }
    }


    //更新商品
    @Override
    @Transactional
    public void UpdateGoods(SpuDTO spuDTO) {

        //更新Spu表
        if (spuDTO.getId() != null) {
            Spu spu = spuDTO.toEntity(Spu.class);
            spu.setUpdateTime(new Date());
            boolean spuResult = this.updateById(spu);
            if (!spuResult) {
                throw new LyException("spu更新失败", 400);
            }
        }


        //更新SpuDetail表
        SpuDetailDTO spuDetailDTO = spuDTO.getSpuDetail();
        if (spuDetailDTO != null) {
            SpuDetail spuDetail = spuDetailDTO.toEntity(SpuDetail.class);
            boolean spuDetailResult = this.spuDetailService.updateById(spuDetail);
            if (!spuDetailResult) {
                throw new LyException("spuDetail更新失败", 400);
            }
        }

        //更新Sku表要考虑是新增，还是下架(删除)，还是修改
        List<SkuDTO> skuDTOList = spuDTO.getSkus();
//        if (!CollectionUtils.isEmpty(skuDTOList)) {
//            //Sku表中saleable值为null就是新增修改，否则就是删除
//            for (SkuDTO skuDTO : skuDTOList) {
//                Boolean saleable = skuDTO.getSaleable();
//                if (saleable == null) {
//                    //新增修改
//                    this.skuService.saveOrUpdate(skuDTO.toEntity(Sku.class));
//                }
//                if (saleable != null) {
//                    //下架(删除)
//                    this.skuService.removeById(skuDTO.toEntity(Sku.class).getId());
//                }
//            }
//        }
        if (!CollectionUtils.isEmpty(skuDTOList)) {
            List<Sku> skuList = skuDTOList.stream().map(skuDTO -> skuDTO.toEntity(Sku.class)).collect(Collectors.toList());
            //将Sku以saleable字段分组，为null(true)则是新增修改，否则就是删除
            Map<Boolean, List<Sku>> booleanListMap =
                     skuList
                    .stream()
                    .collect(Collectors.groupingBy(sku -> sku.getSaleable() == null));

            List<Sku> skuListTODelete = booleanListMap.get(false);
            if (!CollectionUtils.isEmpty(skuListTODelete)) {
                //根据sku得id集合删除对应得sku信息
                this.skuService.removeByIds(skuListTODelete.stream().map(Sku::getId).collect(Collectors.toList()));
            }

            List<Sku> skuListTOSaveOrUpdate = booleanListMap.get(true);
            if (!CollectionUtils.isEmpty(skuListTOSaveOrUpdate)) {
                //新增修改
                this.skuService.saveOrUpdateBatch(skuListTOSaveOrUpdate);
            }
        }
    }
}
